if(!require("plotly")) {install.packages("plotly")}
# install.packages("latex2exp")
# install.packages("BiocManager")
# install.packages("corrplot")
# BiocManager::install("EBImage")
if(!require("lme4")){install.packages("lme4")}
if(!require("lmerTest")){install.packages("lmerTest")}
if(!require("nlme")){install.packages("nlme")}
if(!require("formattable")){install.packages("formattable")}
if(!require("xgboost")){install.packages("xgboost")}
if(!require("processx")) {install.packages("processx")}
if(!require("mefa")){install.packages("mefa")}
library(plotly)
library(lme4)
library(lmerTest)
library(nlme)
library(formattable)
library(xgboost)
### Load libraries
library(EBImage)
library(ggplot2)
library(stringr)
library(gridExtra)
library(latex2exp)
packageVersion('plotly')
[1] ‘4.9.1’
Sys.setenv("plotly_username"="thuynh32")
Sys.setenv("plotly_api_key"="xcSv1yzujDc1IGEwQlr2")
drive1 <- read.csv('../../../data/TT1/preprocessed/Analysis/TT1_Drive_1_PP.csv')
drive2 <- read.csv('../../../data/TT1/preprocessed/Analysis/TT1_Drive_2_PP.csv')
drive3 <- read.csv('../../../data/TT1/preprocessed/Analysis/TT1_Drive_3_PP.csv')
drive4 <- read.csv('../../../data/TT1/preprocessed/Analysis/TT1_Drive_4_PP.csv', stringsAsFactors = T)
dfSeg <- data.frame(rep(1, nrow(drive4)), rep(2, nrow(drive4)), rep(3, nrow(drive4)), rep(4, nrow(drive4)))
names(dfSeg) <- c("Seg1", "Seg2", "Seg3", "Seg4")
combinedDf_Seg1 <- cbind(drive4,
drive1$MeanPP_Seg0,
drive2$MeanPP_Seg1, drive3$MeanPP_Seg1,
drive2$MeanPP_Seg0, drive3$MeanPP_Seg0,
drive2$StdPP, drive3$StdPP,
dfSeg$Seg1
)
combinedDf_Seg2 <- cbind(drive4,
drive1$MeanPP_Seg0,
drive2$MeanPP_Seg2, drive3$MeanPP_Seg2,
drive2$MeanPP_Seg0, drive3$MeanPP_Seg0,
drive2$StdPP, drive3$StdPP,
dfSeg$Seg2
)
combinedDf_Seg3 <- cbind(drive4,
drive1$MeanPP_Seg0,
drive2$MeanPP_Seg3, drive3$MeanPP_Seg3,
drive2$MeanPP_Seg0, drive3$MeanPP_Seg0,
drive2$StdPP, drive3$StdPP,
dfSeg$Seg3
)
combinedDf_Seg4 <- cbind(drive4,
drive1$MeanPP_Seg0,
drive2$MeanPP_Seg4, drive3$MeanPP_Seg4,
drive2$MeanPP_Seg0, drive3$MeanPP_Seg0,
drive2$StdPP, drive3$StdPP,
dfSeg$Seg4
)
names(combinedDf_Seg1) <- c(names(drive4),
"PP_Dev_1_Turning",
"PP_Dev_2_Straight", "PP_Dev_3_Straight",
"PP_Dev_2_Turning", "PP_Dev_3_Turning",
"Std_PP_2", "Std_PP_3", "Segment")
names(combinedDf_Seg2) <- c(names(drive4),
"PP_Dev_1_Turning",
"PP_Dev_2_Straight", "PP_Dev_3_Straight",
"PP_Dev_2_Turning", "PP_Dev_3_Turning",
"Std_PP_2", "Std_PP_3", "Segment")
names(combinedDf_Seg3) <- c(names(drive4),
"PP_Dev_1_Turning",
"PP_Dev_2_Straight", "PP_Dev_3_Straight",
"PP_Dev_2_Turning", "PP_Dev_3_Turning",
"Std_PP_2", "Std_PP_3", "Segment")
names(combinedDf_Seg4) <- c(names(drive4),
"PP_Dev_1_Turning",
"PP_Dev_2_Straight", "PP_Dev_3_Straight",
"PP_Dev_2_Turning", "PP_Dev_3_Turning",
"Std_PP_2", "Std_PP_3", "Segment")
combinedDf_Seg1$Subject <- paste0(as.factor(combinedDf_Seg1$Subject), ".S1")
combinedDf_Seg2$Subject <- paste0(as.factor(combinedDf_Seg2$Subject), ".S2")
combinedDf_Seg3$Subject <- paste0(as.factor(combinedDf_Seg3$Subject), ".S3")
combinedDf_Seg4$Subject <- paste0(as.factor(combinedDf_Seg4$Subject), ".S4")
combinedDf <- rbind(combinedDf_Seg1, combinedDf_Seg2, combinedDf_Seg3, combinedDf_Seg4)
combinedDf$Subject <- paste0("#", str_pad(combinedDf$Subject, 2, pad="0"))
combinedDf$Segment <- as.factor(combinedDf$Segment)
combinedDf_NoStressor <- combinedDf[combinedDf$Activity == "NO",]
combinedDf_Cognitive <- combinedDf[combinedDf$Activity == "C",]
combinedDf_Motoric <- combinedDf[combinedDf$Activity == "M",]
# combinedDf_NoStressor$Subject <- as.factor(combinedDf_NoStressor$Subject)
# combinedDf_Cognitive$Subject <- as.factor(combinedDf_Cognitive$Subject)
# combinedDf_Motoric$Subject <- as.factor(combinedDf_Motoric$Subject)
COLOR_NORMAL <- list(color='rgb(120,120,120)')
COLOR_COGNITIVE <- list(color='rgb(158,202,225)')
COLOR_MOTORIC <- list(color='rgb(58,200,225)')
COLOR_FAILURE <- list(color='red')
THRESHOLD_MILD = 0.07
THRESHOLD_EXTREME = 0.2
MARKER_LINE_MILD = list(color="blue")
MARKER_LINE_EXTREME = list(color="red")
yAxis <- list(title = 'Perinasal Perspiration (Log)', range=c(-0.3, 0.5))
fig_NoStressor <- plot_ly(combinedDf_NoStressor, x = ~Subject, y = ~PP_Dev_2_Straight, type = 'bar', name = 'Cognitive - Mean PP (Straight)', marker=COLOR_COGNITIVE) %>%
add_trace(y = ~PP_Dev_3_Straight, name = 'Motoric - Mean PP (Straight)', marker=COLOR_MOTORIC) %>%
add_trace(y = ~PP_Dev_2_Turning, name = 'Cognitive - Mean PP (Turning)', marker=COLOR_COGNITIVE) %>%
add_trace(y = ~PP_Dev_3_Turning, name = 'Motoric - Mean PP (Turning)', marker=COLOR_MOTORIC) %>%
add_trace(y = ~PP_Dev, name = 'Failure - PP Deviation', marker=COLOR_FAILURE) %>%
add_segments(x="#1.S1", xend="#7.S4", y = THRESHOLD_MILD, yend = THRESHOLD_MILD, name="Threshold: Mild Change of PP",
line=list(color="blue", dash = 'dot')) %>%
# add_segments(x="#01", xend="#41", y = THRESHOLD_EXTREME, yend = THRESHOLD_EXTREME, name="Threshold: Extreme Change of PP",
# line=list(color="darkred", dash = 'dot')) %>%
layout(yaxis = yAxis, barmode = 'group', title="Failure Driving \n Group=No Stressor")
htmltools::tagList(fig_NoStressor)
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
yAxis <- list(title = 'Perinasal Perspiration (Log)', range=c(-0.3, 0.3))
fig_Cognitive <- plot_ly(combinedDf_Cognitive, x = ~Subject, y = ~PP_Dev_2_Straight, type = 'bar', name = 'Cognitive - Mean PP (Straight)', marker=COLOR_COGNITIVE) %>%
add_trace(y = ~PP_Dev_3_Straight, name = 'Motoric - Mean PP (Straight)', marker=COLOR_MOTORIC) %>%
add_trace(y = ~PP_Dev_2_Turning, name = 'Cognitive - Mean PP (Turning)', marker=COLOR_COGNITIVE) %>%
add_trace(y = ~PP_Dev_3_Turning, name = 'Motoric - Mean PP (Turning)', marker=COLOR_MOTORIC) %>%
add_trace(y = ~PP_Dev, name = 'Failure - PP Deviation', marker=COLOR_FAILURE) %>%
add_segments(x="#12.S1", xend="#3.S4", y = THRESHOLD_MILD, yend = THRESHOLD_MILD, name="Threshold: Mild Change of PP",
line=list(color="blue", dash = 'dot')) %>%
# add_segments(x="#02", xend="#22", y = THRESHOLD_EXTREME, yend = THRESHOLD_EXTREME, name="Threshold: Extreme Change of PP",
# line=list(color="darkred", dash = 'dot')) %>%
layout(yaxis = yAxis, barmode = 'group', title="Failure Driving \n Group=Cognitive")
htmltools::tagList(fig_Cognitive)
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
yAxis <- list(title = 'Perinasal Perspiration (Log)', range=c(-0.3, 0.5))
fig_Motoric <- plot_ly(combinedDf_Motoric, x = ~Subject, y = ~PP_Dev_2_Straight, type = 'bar', name = 'Cognitive - Mean PP (Straight)', marker=COLOR_COGNITIVE) %>%
add_trace(y = ~PP_Dev_3_Straight, name = 'Motoric - Mean PP (Straight)', marker=COLOR_MOTORIC) %>%
add_trace(y = ~PP_Dev_2_Turning, name = 'Cognitive - Mean PP (Turning)', marker=COLOR_COGNITIVE) %>%
add_trace(y = ~PP_Dev_3_Turning, name = 'Motoric - Mean PP (Turning)', marker=COLOR_MOTORIC) %>%
add_trace(y = ~PP_Dev, name = 'Failure - PP Deviation', marker=COLOR_FAILURE) %>%
add_segments(x="#24.S1", xend="#9.S4", y = THRESHOLD_MILD, yend = THRESHOLD_MILD, name="Threshold: Mild Change of PP",
line=list(color="blue", dash = 'dot')) %>%
# add_segments(x="#05", xend="#31", y = THRESHOLD_EXTREME, yend = THRESHOLD_EXTREME, name="Threshold: Extreme Change of PP",
# line=list(color="darkred", dash = 'dot')) %>%
layout(yaxis = yAxis, barmode = 'group', title="Failure Driving \n Group: Motoric")
htmltools::tagList(fig_Motoric)
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
A marker object has been specified, but markers is not in the mode
Adding markers to the mode...
library(nlme)
combinedDf$Subject = as.factor(combinedDf$Subject)
combinedDf$Activity = as.factor(combinedDf$Activity)
combinedDf$PP_Dev_Group = ifelse(combinedDf$PP_Dev > THRESHOLD_MILD, 1, 0)
model = lme(PP_Dev ~
abs(PP_Dev_2_Straight)
+ abs(PP_Dev_3_Straight)
+ abs(PP_Dev_2_Turning)
+ abs(PP_Dev_3_Turning)
+ factor(Activity),
random=~1|Subject,
data=combinedDf,
method="REML")
# anova(model)
summary(model)
Linear mixed-effects model fit by REML
Data: combinedDf
Random effects:
Formula: ~1 | Subject
(Intercept) Residual
StdDev: 0.07378811 0.02767054
Fixed effects: PP_Dev ~ abs(PP_Dev_2_Straight) + abs(PP_Dev_3_Straight) + abs(PP_Dev_2_Turning) + abs(PP_Dev_3_Turning) + factor(Activity)
Correlation:
(Intr) a(PP_D_2_S a(PP_D_3_S a(PP_D_2_T a(PP_D_3_T fc(A)M
abs(PP_Dev_2_Straight) 0.255
abs(PP_Dev_3_Straight) -0.008 -0.137
abs(PP_Dev_2_Turning) -0.240 -0.570 -0.341
abs(PP_Dev_3_Turning) -0.556 -0.161 -0.456 0.053
factor(Activity)M -0.421 -0.082 0.073 -0.177 0.062
factor(Activity)NO -0.279 -0.023 0.305 -0.389 -0.102 0.544
Standardized Within-Group Residuals:
Min Q1 Med Q3 Max
-0.62224161 -0.30808560 0.03485727 0.22938155 0.62177482
Number of Observations: 84
Number of Groups: 84
plot(model)

model = lme(PP_Dev ~
abs(PP_Dev_2_Turning)
+ factor(Activity),
random=~1|Subject,
data=combinedDf,
method="REML")
# anova(model)
summary(model)
Linear mixed-effects model fit by REML
Data: combinedDf
Random effects:
Formula: ~1 | Subject
(Intercept) Residual
StdDev: 0.07514543 0.02817954
Fixed effects: PP_Dev ~ abs(PP_Dev_2_Turning) + factor(Activity)
Correlation:
(Intr) a(PP_D fc(A)M
abs(PP_Dev_2_Turning) -0.497
factor(Activity)M -0.457 -0.270
factor(Activity)NO -0.346 -0.423 0.550
Standardized Within-Group Residuals:
Min Q1 Med Q3 Max
-0.53252940 -0.23585738 0.02008019 0.22292732 0.55040771
Number of Observations: 84
Number of Groups: 84
plot(model)

model = lme(PP_Dev ~
PP_Dev_2_Straight +
PP_Dev_3_Straight +
PP_Dev_1_Turning +
PP_Dev_2_Turning +
PP_Dev_3_Turning +
Std_PP_2 +
Std_PP_3 +
factor(Activity),
random=~1|Subject,
data=combinedDf,
method="REML")
# anova(model)
summary(model)
Linear mixed-effects model fit by REML
Data: combinedDf
Random effects:
Formula: ~1 | Subject
(Intercept) Residual
StdDev: 0.07042784 0.02641044
Fixed effects: PP_Dev ~ PP_Dev_2_Straight + PP_Dev_3_Straight + PP_Dev_1_Turning + PP_Dev_2_Turning + PP_Dev_3_Turning + Std_PP_2 + Std_PP_3 + factor(Activity)
Correlation:
(Intr) PP_D_2_S PP_D_3_S PP_D_1 PP_D_2_T PP_D_3_T S_PP_2 S_PP_3 fc(A)M
PP_Dev_2_Straight -0.157
PP_Dev_3_Straight 0.048 -0.217
PP_Dev_1_Turning -0.818 0.257 0.106
PP_Dev_2_Turning 0.445 -0.777 0.007 -0.487
PP_Dev_3_Turning -0.164 0.280 -0.639 -0.197 -0.358
Std_PP_2 0.261 -0.458 -0.156 -0.367 0.743 -0.173
Std_PP_3 -0.846 0.398 0.057 0.750 -0.721 0.160 -0.640
factor(Activity)M 0.182 -0.232 0.340 -0.129 0.171 -0.267 0.108 -0.347
factor(Activity)NO -0.251 -0.074 0.268 0.163 -0.194 -0.101 -0.368 0.263 0.394
Standardized Within-Group Residuals:
Min Q1 Med Q3 Max
-0.67464572 -0.25005516 0.08544853 0.18066413 0.65739692
Number of Observations: 84
Number of Groups: 84
plot(model)

Machine Learning
combinedDf$PP_Dev <- NULL
combinedDf$Subject <- NULL
combinedDf$Activity_NO <- ifelse(combinedDf$Activity == "NO", 1, 0)
combinedDf$Activity_C <- ifelse(combinedDf$Activity == "C", 1, 0)
combinedDf$Activity_M <- ifelse(combinedDf$Activity == "M", 1, 0)
combinedDf$Activity <- NULL
combinedDf$InSegment1 <- ifelse(combinedDf$Segment == 1, 1, 0)
combinedDf$InSegment2 <- ifelse(combinedDf$Segment == 2, 1, 0)
combinedDf$InSegment3 <- ifelse(combinedDf$Segment == 3, 1, 0)
combinedDf$InSegment4 <- ifelse(combinedDf$Segment == 4, 1, 0)
combinedDf$Segment <- NULL
combinedDf$Class <- ifelse(combinedDf$PP_Dev_Group == 1, T, F)
combinedDf$PP_Dev_Group <- NULL
# library(mefa)
# combinedDf <- rep(combinedDf, 10)
# s=55, f=4
set.seed(5151)
n_folds <- 5
params <- param <- list(objective = "binary:logistic",
booster = "gbtree",
eval_metric = "auc",
eta = 0.1,
max_depth = 8,
alpha = 1,
lambda = 0,
gamma = 0.3,
min_child_weight = 0.3,
subsample = 1,
colsample_bytree = 0.5)
# xgb_m <- xgb.cv( params = param,
# data = as.matrix(combinedDf %>% select(-Class)) ,
# label = combinedDf$Class,
# nrounds = 100,
# verbose = F,
# prediction = T,
# maximize = T,
# nfold = n_folds,
# metrics = "auc",
# early_stopping_rounds = 100,
# stratified = F,
# scale_pos_weight = 0.5)
#
# # xgb_m$evaluation_log[xgb_m$best_iteration,"test_auc_mean"]
# xgb_m$evaluation_log[xgb_m$best_iteration,]
# Error
ml_data <- as.matrix(combinedDf %>% select(-Class))
xgb_m <- xgb.cv( params = param,
data = ml_data ,
label = combinedDf$Class,
nrounds = 500,
verbose = F,
prediction = T,
maximize = T,
nfold = n_folds,
metrics = c("auc", "error"),
early_stopping_rounds = 100,
stratified = F,
scale_pos_weight = 3.05)
# xgb_m$evaluation_log[xgb_m$best_iteration,"test_auc_mean"]
xgb_m$evaluation_log[xgb_m$best_iteration,]
NA
library(pROC)
# it = which.max(xgb_m$evaluation_log$test_auc_mean)
# best.iter = xgb_m$evaluation_log$iter[it]
# best.iter
plot(pROC::roc(response = ifelse(combinedDf$Class==T, 1, 0),
predictor = xgb_m$pred,
levels=c(0, 1)),
lwd=1.5)
Setting direction: controls < cases

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CmlmKCFyZXF1aXJlKCJwbG90bHkiKSkge2luc3RhbGwucGFja2FnZXMoInBsb3RseSIpfQoKIyBpbnN0YWxsLnBhY2thZ2VzKCJsYXRleDJleHAiKQojIGluc3RhbGwucGFja2FnZXMoIkJpb2NNYW5hZ2VyIikgCiMgaW5zdGFsbC5wYWNrYWdlcygiY29ycnBsb3QiKQojIEJpb2NNYW5hZ2VyOjppbnN0YWxsKCJFQkltYWdlIikKCmlmKCFyZXF1aXJlKCJsbWU0Iikpe2luc3RhbGwucGFja2FnZXMoImxtZTQiKX0KaWYoIXJlcXVpcmUoImxtZXJUZXN0Iikpe2luc3RhbGwucGFja2FnZXMoImxtZXJUZXN0Iil9CmlmKCFyZXF1aXJlKCJubG1lIikpe2luc3RhbGwucGFja2FnZXMoIm5sbWUiKX0KaWYoIXJlcXVpcmUoImZvcm1hdHRhYmxlIikpe2luc3RhbGwucGFja2FnZXMoImZvcm1hdHRhYmxlIil9CmlmKCFyZXF1aXJlKCJ4Z2Jvb3N0Iikpe2luc3RhbGwucGFja2FnZXMoInhnYm9vc3QiKX0KaWYoIXJlcXVpcmUoInByb2Nlc3N4IikpIHtpbnN0YWxsLnBhY2thZ2VzKCJwcm9jZXNzeCIpfQoKaWYoIXJlcXVpcmUoIm1lZmEiKSl7aW5zdGFsbC5wYWNrYWdlcygibWVmYSIpfQoKbGlicmFyeShwbG90bHkpCmxpYnJhcnkobG1lNCkKbGlicmFyeShsbWVyVGVzdCkKbGlicmFyeShubG1lKQpsaWJyYXJ5KGZvcm1hdHRhYmxlKQpsaWJyYXJ5KHhnYm9vc3QpCgojIyMgTG9hZCBsaWJyYXJpZXMKbGlicmFyeShFQkltYWdlKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkobGF0ZXgyZXhwKQpwYWNrYWdlVmVyc2lvbigncGxvdGx5JykKU3lzLnNldGVudigicGxvdGx5X3VzZXJuYW1lIj0idGh1eW5oMzIiKQpTeXMuc2V0ZW52KCJwbG90bHlfYXBpX2tleSI9InhjU3YxeXp1akRjMUlHRXdRbHIyIikKCmBgYAoKYGBge3J9CmRyaXZlMSA8LSByZWFkLmNzdignLi4vLi4vLi4vZGF0YS9UVDEvcHJlcHJvY2Vzc2VkL0FuYWx5c2lzL1RUMV9Ecml2ZV8xX1BQLmNzdicpCmRyaXZlMiA8LSByZWFkLmNzdignLi4vLi4vLi4vZGF0YS9UVDEvcHJlcHJvY2Vzc2VkL0FuYWx5c2lzL1RUMV9Ecml2ZV8yX1BQLmNzdicpCmRyaXZlMyA8LSByZWFkLmNzdignLi4vLi4vLi4vZGF0YS9UVDEvcHJlcHJvY2Vzc2VkL0FuYWx5c2lzL1RUMV9Ecml2ZV8zX1BQLmNzdicpCmRyaXZlNCA8LSByZWFkLmNzdignLi4vLi4vLi4vZGF0YS9UVDEvcHJlcHJvY2Vzc2VkL0FuYWx5c2lzL1RUMV9Ecml2ZV80X1BQLmNzdicsIHN0cmluZ3NBc0ZhY3RvcnMgPSBUKQpgYGAKCmBgYHtyfQpkZlNlZyA8LSBkYXRhLmZyYW1lKHJlcCgxLCBucm93KGRyaXZlNCkpLCByZXAoMiwgbnJvdyhkcml2ZTQpKSwgcmVwKDMsIG5yb3coZHJpdmU0KSksIHJlcCg0LCBucm93KGRyaXZlNCkpKQpuYW1lcyhkZlNlZykgPC0gYygiU2VnMSIsICJTZWcyIiwgIlNlZzMiLCAiU2VnNCIpCgpjb21iaW5lZERmX1NlZzEgPC0gY2JpbmQoZHJpdmU0LCAKICAgICAgICAgICAgICAgICAgICBkcml2ZTEkTWVhblBQX1NlZzAsIAogICAgICAgICAgICAgICAgICAgIGRyaXZlMiRNZWFuUFBfU2VnMSwgZHJpdmUzJE1lYW5QUF9TZWcxLCAKICAgICAgICAgICAgICAgICAgICBkcml2ZTIkTWVhblBQX1NlZzAsIGRyaXZlMyRNZWFuUFBfU2VnMCwKICAgICAgICAgICAgICAgICAgICBkcml2ZTIkU3RkUFAsIGRyaXZlMyRTdGRQUCwKICAgICAgICAgICAgICAgICAgICBkZlNlZyRTZWcxCiAgICAgICAgICAgICAgICAgICkKY29tYmluZWREZl9TZWcyIDwtIGNiaW5kKGRyaXZlNCwgCiAgICAgICAgICAgICAgICAgICAgZHJpdmUxJE1lYW5QUF9TZWcwLCAKICAgICAgICAgICAgICAgICAgICBkcml2ZTIkTWVhblBQX1NlZzIsIGRyaXZlMyRNZWFuUFBfU2VnMiwgCiAgICAgICAgICAgICAgICAgICAgZHJpdmUyJE1lYW5QUF9TZWcwLCBkcml2ZTMkTWVhblBQX1NlZzAsCiAgICAgICAgICAgICAgICAgICAgZHJpdmUyJFN0ZFBQLCBkcml2ZTMkU3RkUFAsCiAgICAgICAgICAgICAgICAgICAgZGZTZWckU2VnMgogICAgICAgICAgICAgICAgICApCmNvbWJpbmVkRGZfU2VnMyA8LSBjYmluZChkcml2ZTQsIAogICAgICAgICAgICAgICAgICAgIGRyaXZlMSRNZWFuUFBfU2VnMCwgCiAgICAgICAgICAgICAgICAgICAgZHJpdmUyJE1lYW5QUF9TZWczLCBkcml2ZTMkTWVhblBQX1NlZzMsIAogICAgICAgICAgICAgICAgICAgIGRyaXZlMiRNZWFuUFBfU2VnMCwgZHJpdmUzJE1lYW5QUF9TZWcwLAogICAgICAgICAgICAgICAgICAgIGRyaXZlMiRTdGRQUCwgZHJpdmUzJFN0ZFBQLAogICAgICAgICAgICAgICAgICAgIGRmU2VnJFNlZzMKICAgICAgICAgICAgICAgICAgKQpjb21iaW5lZERmX1NlZzQgPC0gY2JpbmQoZHJpdmU0LCAKICAgICAgICAgICAgICAgICAgICBkcml2ZTEkTWVhblBQX1NlZzAsIAogICAgICAgICAgICAgICAgICAgIGRyaXZlMiRNZWFuUFBfU2VnNCwgZHJpdmUzJE1lYW5QUF9TZWc0LCAKICAgICAgICAgICAgICAgICAgICBkcml2ZTIkTWVhblBQX1NlZzAsIGRyaXZlMyRNZWFuUFBfU2VnMCwKICAgICAgICAgICAgICAgICAgICBkcml2ZTIkU3RkUFAsIGRyaXZlMyRTdGRQUCwKICAgICAgICAgICAgICAgICAgICBkZlNlZyRTZWc0CiAgICAgICAgICAgICAgICAgICkKCm5hbWVzKGNvbWJpbmVkRGZfU2VnMSkgPC0gYyhuYW1lcyhkcml2ZTQpLCAKICAgICAgICAgICAgICAgICAgICAgICAiUFBfRGV2XzFfVHVybmluZyIsCiAgICAgICAgICAgICAgICAgICAgICAgIlBQX0Rldl8yX1N0cmFpZ2h0IiwgIlBQX0Rldl8zX1N0cmFpZ2h0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgIlBQX0Rldl8yX1R1cm5pbmciLCAiUFBfRGV2XzNfVHVybmluZyIsIAogICAgICAgICAgICAgICAgICAgICAgICJTdGRfUFBfMiIsICJTdGRfUFBfMyIsICJTZWdtZW50IikKbmFtZXMoY29tYmluZWREZl9TZWcyKSA8LSBjKG5hbWVzKGRyaXZlNCksIAogICAgICAgICAgICAgICAgICAgICAgICJQUF9EZXZfMV9UdXJuaW5nIiwKICAgICAgICAgICAgICAgICAgICAgICAiUFBfRGV2XzJfU3RyYWlnaHQiLCAiUFBfRGV2XzNfU3RyYWlnaHQiLCAKICAgICAgICAgICAgICAgICAgICAgICAiUFBfRGV2XzJfVHVybmluZyIsICJQUF9EZXZfM19UdXJuaW5nIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIlN0ZF9QUF8yIiwgIlN0ZF9QUF8zIiwgIlNlZ21lbnQiKQpuYW1lcyhjb21iaW5lZERmX1NlZzMpIDwtIGMobmFtZXMoZHJpdmU0KSwgCiAgICAgICAgICAgICAgICAgICAgICAgIlBQX0Rldl8xX1R1cm5pbmciLAogICAgICAgICAgICAgICAgICAgICAgICJQUF9EZXZfMl9TdHJhaWdodCIsICJQUF9EZXZfM19TdHJhaWdodCIsIAogICAgICAgICAgICAgICAgICAgICAgICJQUF9EZXZfMl9UdXJuaW5nIiwgIlBQX0Rldl8zX1R1cm5pbmciLCAKICAgICAgICAgICAgICAgICAgICAgICAiU3RkX1BQXzIiLCAiU3RkX1BQXzMiLCAiU2VnbWVudCIpCm5hbWVzKGNvbWJpbmVkRGZfU2VnNCkgPC0gYyhuYW1lcyhkcml2ZTQpLCAKICAgICAgICAgICAgICAgICAgICAgICAiUFBfRGV2XzFfVHVybmluZyIsCiAgICAgICAgICAgICAgICAgICAgICAgIlBQX0Rldl8yX1N0cmFpZ2h0IiwgIlBQX0Rldl8zX1N0cmFpZ2h0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgIlBQX0Rldl8yX1R1cm5pbmciLCAiUFBfRGV2XzNfVHVybmluZyIsIAogICAgICAgICAgICAgICAgICAgICAgICJTdGRfUFBfMiIsICJTdGRfUFBfMyIsICJTZWdtZW50IikKCmNvbWJpbmVkRGZfU2VnMSRTdWJqZWN0IDwtIHBhc3RlMChhcy5mYWN0b3IoY29tYmluZWREZl9TZWcxJFN1YmplY3QpLCAiLlMxIikKY29tYmluZWREZl9TZWcyJFN1YmplY3QgPC0gcGFzdGUwKGFzLmZhY3Rvcihjb21iaW5lZERmX1NlZzIkU3ViamVjdCksICIuUzIiKQpjb21iaW5lZERmX1NlZzMkU3ViamVjdCA8LSBwYXN0ZTAoYXMuZmFjdG9yKGNvbWJpbmVkRGZfU2VnMyRTdWJqZWN0KSwgIi5TMyIpCmNvbWJpbmVkRGZfU2VnNCRTdWJqZWN0IDwtIHBhc3RlMChhcy5mYWN0b3IoY29tYmluZWREZl9TZWc0JFN1YmplY3QpLCAiLlM0IikKCmNvbWJpbmVkRGYgPC0gcmJpbmQoY29tYmluZWREZl9TZWcxLCBjb21iaW5lZERmX1NlZzIsIGNvbWJpbmVkRGZfU2VnMywgY29tYmluZWREZl9TZWc0KQoKY29tYmluZWREZiRTdWJqZWN0IDwtIHBhc3RlMCgiIyIsIHN0cl9wYWQoY29tYmluZWREZiRTdWJqZWN0LCAyLCBwYWQ9IjAiKSkKY29tYmluZWREZiRTZWdtZW50IDwtIGFzLmZhY3Rvcihjb21iaW5lZERmJFNlZ21lbnQpCmBgYAoKYGBge3J9CmNvbWJpbmVkRGZfTm9TdHJlc3NvciA8LSBjb21iaW5lZERmW2NvbWJpbmVkRGYkQWN0aXZpdHkgPT0gIk5PIixdCmNvbWJpbmVkRGZfQ29nbml0aXZlIDwtIGNvbWJpbmVkRGZbY29tYmluZWREZiRBY3Rpdml0eSA9PSAiQyIsXQpjb21iaW5lZERmX01vdG9yaWMgPC0gY29tYmluZWREZltjb21iaW5lZERmJEFjdGl2aXR5ID09ICJNIixdCgojIGNvbWJpbmVkRGZfTm9TdHJlc3NvciRTdWJqZWN0IDwtIGFzLmZhY3Rvcihjb21iaW5lZERmX05vU3RyZXNzb3IkU3ViamVjdCkKIyBjb21iaW5lZERmX0NvZ25pdGl2ZSRTdWJqZWN0IDwtIGFzLmZhY3Rvcihjb21iaW5lZERmX0NvZ25pdGl2ZSRTdWJqZWN0KQojIGNvbWJpbmVkRGZfTW90b3JpYyRTdWJqZWN0IDwtIGFzLmZhY3Rvcihjb21iaW5lZERmX01vdG9yaWMkU3ViamVjdCkKYGBgCgpgYGB7cn0KQ09MT1JfTk9STUFMIDwtIGxpc3QoY29sb3I9J3JnYigxMjAsMTIwLDEyMCknKQpDT0xPUl9DT0dOSVRJVkUgPC0gbGlzdChjb2xvcj0ncmdiKDE1OCwyMDIsMjI1KScpCkNPTE9SX01PVE9SSUMgPC0gbGlzdChjb2xvcj0ncmdiKDU4LDIwMCwyMjUpJykKQ09MT1JfRkFJTFVSRSA8LSBsaXN0KGNvbG9yPSdyZWQnKQoKVEhSRVNIT0xEX01JTEQgPSAwLjA3ClRIUkVTSE9MRF9FWFRSRU1FID0gMC4yCgpNQVJLRVJfTElORV9NSUxEID0gbGlzdChjb2xvcj0iYmx1ZSIpCk1BUktFUl9MSU5FX0VYVFJFTUUgPSBsaXN0KGNvbG9yPSJyZWQiKQpgYGAKCmBgYHtyLCB3YXJuaW5nPUZ9CnlBeGlzIDwtIGxpc3QodGl0bGUgPSAnUGVyaW5hc2FsIFBlcnNwaXJhdGlvbiAoTG9nKScsIHJhbmdlPWMoLTAuMywgMC41KSkKCmZpZ19Ob1N0cmVzc29yIDwtIHBsb3RfbHkoY29tYmluZWREZl9Ob1N0cmVzc29yLCB4ID0gflN1YmplY3QsIHkgPSB+UFBfRGV2XzJfU3RyYWlnaHQsIHR5cGUgPSAnYmFyJywgbmFtZSA9ICdDb2duaXRpdmUgLSBNZWFuIFBQIChTdHJhaWdodCknLCBtYXJrZXI9Q09MT1JfQ09HTklUSVZFKSAlPiUKICBhZGRfdHJhY2UoeSA9IH5QUF9EZXZfM19TdHJhaWdodCwgbmFtZSA9ICdNb3RvcmljIC0gTWVhbiBQUCAoU3RyYWlnaHQpJywgbWFya2VyPUNPTE9SX01PVE9SSUMpICU+JSAKICBhZGRfdHJhY2UoeSA9IH5QUF9EZXZfMl9UdXJuaW5nLCBuYW1lID0gJ0NvZ25pdGl2ZSAtIE1lYW4gUFAgKFR1cm5pbmcpJywgbWFya2VyPUNPTE9SX0NPR05JVElWRSkgJT4lIAogIGFkZF90cmFjZSh5ID0gflBQX0Rldl8zX1R1cm5pbmcsIG5hbWUgPSAnTW90b3JpYyAtIE1lYW4gUFAgKFR1cm5pbmcpJywgbWFya2VyPUNPTE9SX01PVE9SSUMpICU+JSAKICBhZGRfdHJhY2UoeSA9IH5QUF9EZXYsIG5hbWUgPSAnRmFpbHVyZSAtIFBQIERldmlhdGlvbicsIG1hcmtlcj1DT0xPUl9GQUlMVVJFKSAlPiUgCiAgYWRkX3NlZ21lbnRzKHg9IiMxLlMxIiwgeGVuZD0iIzcuUzQiLCB5ID0gVEhSRVNIT0xEX01JTEQsIHllbmQgPSBUSFJFU0hPTERfTUlMRCwgbmFtZT0iVGhyZXNob2xkOiBNaWxkIENoYW5nZSBvZiBQUCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmU9bGlzdChjb2xvcj0iYmx1ZSIsIGRhc2ggPSAnZG90JykpICU+JQogICMgYWRkX3NlZ21lbnRzKHg9IiMwMSIsIHhlbmQ9IiM0MSIsIHkgPSBUSFJFU0hPTERfRVhUUkVNRSwgeWVuZCA9IFRIUkVTSE9MRF9FWFRSRU1FLCBuYW1lPSJUaHJlc2hvbGQ6IEV4dHJlbWUgQ2hhbmdlIG9mIFBQIiwKICAjICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lPWxpc3QoY29sb3I9ImRhcmtyZWQiLCBkYXNoID0gJ2RvdCcpKSAlPiUKICBsYXlvdXQoeWF4aXMgPSB5QXhpcywgYmFybW9kZSA9ICdncm91cCcsIHRpdGxlPSJGYWlsdXJlIERyaXZpbmcgXG4gR3JvdXA9Tm8gU3RyZXNzb3IiKQoKaHRtbHRvb2xzOjp0YWdMaXN0KGZpZ19Ob1N0cmVzc29yKQpgYGAKCmBgYHtyLCB3YXJuaW5nPUZ9CnlBeGlzIDwtIGxpc3QodGl0bGUgPSAnUGVyaW5hc2FsIFBlcnNwaXJhdGlvbiAoTG9nKScsIHJhbmdlPWMoLTAuMywgMC4zKSkKCmZpZ19Db2duaXRpdmUgPC0gcGxvdF9seShjb21iaW5lZERmX0NvZ25pdGl2ZSwgeCA9IH5TdWJqZWN0LCB5ID0gflBQX0Rldl8yX1N0cmFpZ2h0LCB0eXBlID0gJ2JhcicsIG5hbWUgPSAnQ29nbml0aXZlIC0gTWVhbiBQUCAoU3RyYWlnaHQpJywgbWFya2VyPUNPTE9SX0NPR05JVElWRSkgJT4lCiAgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzNfU3RyYWlnaHQsIG5hbWUgPSAnTW90b3JpYyAtIE1lYW4gUFAgKFN0cmFpZ2h0KScsIG1hcmtlcj1DT0xPUl9NT1RPUklDKSAlPiUgCiAgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzJfVHVybmluZywgbmFtZSA9ICdDb2duaXRpdmUgLSBNZWFuIFBQIChUdXJuaW5nKScsIG1hcmtlcj1DT0xPUl9DT0dOSVRJVkUpICU+JSAKICBhZGRfdHJhY2UoeSA9IH5QUF9EZXZfM19UdXJuaW5nLCBuYW1lID0gJ01vdG9yaWMgLSBNZWFuIFBQIChUdXJuaW5nKScsIG1hcmtlcj1DT0xPUl9NT1RPUklDKSAlPiUgCiAgYWRkX3RyYWNlKHkgPSB+UFBfRGV2LCBuYW1lID0gJ0ZhaWx1cmUgLSBQUCBEZXZpYXRpb24nLCBtYXJrZXI9Q09MT1JfRkFJTFVSRSkgJT4lIAogIGFkZF9zZWdtZW50cyh4PSIjMTIuUzEiLCB4ZW5kPSIjMy5TNCIsIHkgPSBUSFJFU0hPTERfTUlMRCwgeWVuZCA9IFRIUkVTSE9MRF9NSUxELCBuYW1lPSJUaHJlc2hvbGQ6IE1pbGQgQ2hhbmdlIG9mIFBQIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgZGFzaCA9ICdkb3QnKSkgJT4lCiAgIyBhZGRfc2VnbWVudHMoeD0iIzAyIiwgeGVuZD0iIzIyIiwgeSA9IFRIUkVTSE9MRF9FWFRSRU1FLCB5ZW5kID0gVEhSRVNIT0xEX0VYVFJFTUUsIG5hbWU9IlRocmVzaG9sZDogRXh0cmVtZSBDaGFuZ2Ugb2YgUFAiLAogICMgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmU9bGlzdChjb2xvcj0iZGFya3JlZCIsIGRhc2ggPSAnZG90JykpICU+JQogIGxheW91dCh5YXhpcyA9IHlBeGlzLCBiYXJtb2RlID0gJ2dyb3VwJywgdGl0bGU9IkZhaWx1cmUgRHJpdmluZyBcbiBHcm91cD1Db2duaXRpdmUiKQoKaHRtbHRvb2xzOjp0YWdMaXN0KGZpZ19Db2duaXRpdmUpCmBgYAoKCgpgYGB7ciwgd2FybmluZz1GfQp5QXhpcyA8LSBsaXN0KHRpdGxlID0gJ1BlcmluYXNhbCBQZXJzcGlyYXRpb24gKExvZyknLCByYW5nZT1jKC0wLjMsIDAuNSkpCgpmaWdfTW90b3JpYyA8LSBwbG90X2x5KGNvbWJpbmVkRGZfTW90b3JpYywgeCA9IH5TdWJqZWN0LCB5ID0gflBQX0Rldl8yX1N0cmFpZ2h0LCB0eXBlID0gJ2JhcicsIG5hbWUgPSAnQ29nbml0aXZlIC0gTWVhbiBQUCAoU3RyYWlnaHQpJywgbWFya2VyPUNPTE9SX0NPR05JVElWRSkgJT4lCiAgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzNfU3RyYWlnaHQsIG5hbWUgPSAnTW90b3JpYyAtIE1lYW4gUFAgKFN0cmFpZ2h0KScsIG1hcmtlcj1DT0xPUl9NT1RPUklDKSAlPiUgCiAgYWRkX3RyYWNlKHkgPSB+UFBfRGV2XzJfVHVybmluZywgbmFtZSA9ICdDb2duaXRpdmUgLSBNZWFuIFBQIChUdXJuaW5nKScsIG1hcmtlcj1DT0xPUl9DT0dOSVRJVkUpICU+JSAKICBhZGRfdHJhY2UoeSA9IH5QUF9EZXZfM19UdXJuaW5nLCBuYW1lID0gJ01vdG9yaWMgLSBNZWFuIFBQIChUdXJuaW5nKScsIG1hcmtlcj1DT0xPUl9NT1RPUklDKSAlPiUgCiAgYWRkX3RyYWNlKHkgPSB+UFBfRGV2LCBuYW1lID0gJ0ZhaWx1cmUgLSBQUCBEZXZpYXRpb24nLCBtYXJrZXI9Q09MT1JfRkFJTFVSRSkgJT4lIAogIGFkZF9zZWdtZW50cyh4PSIjMjQuUzEiLCB4ZW5kPSIjOS5TNCIsIHkgPSBUSFJFU0hPTERfTUlMRCwgeWVuZCA9IFRIUkVTSE9MRF9NSUxELCBuYW1lPSJUaHJlc2hvbGQ6IE1pbGQgQ2hhbmdlIG9mIFBQIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgZGFzaCA9ICdkb3QnKSkgJT4lCiAgIyBhZGRfc2VnbWVudHMoeD0iIzA1IiwgeGVuZD0iIzMxIiwgeSA9IFRIUkVTSE9MRF9FWFRSRU1FLCB5ZW5kID0gVEhSRVNIT0xEX0VYVFJFTUUsIG5hbWU9IlRocmVzaG9sZDogRXh0cmVtZSBDaGFuZ2Ugb2YgUFAiLAogICMgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmU9bGlzdChjb2xvcj0iZGFya3JlZCIsIGRhc2ggPSAnZG90JykpICU+JQogIGxheW91dCh5YXhpcyA9IHlBeGlzLCBiYXJtb2RlID0gJ2dyb3VwJywgdGl0bGU9IkZhaWx1cmUgRHJpdmluZyBcbiBHcm91cDogTW90b3JpYyIpCgpodG1sdG9vbHM6OnRhZ0xpc3QoZmlnX01vdG9yaWMpCmBgYAoKCmBgYHtyfQpsaWJyYXJ5KG5sbWUpCgpjb21iaW5lZERmJFN1YmplY3QgPSBhcy5mYWN0b3IoY29tYmluZWREZiRTdWJqZWN0KQpjb21iaW5lZERmJEFjdGl2aXR5ID0gYXMuZmFjdG9yKGNvbWJpbmVkRGYkQWN0aXZpdHkpCgpjb21iaW5lZERmJFBQX0Rldl9Hcm91cCA9IGlmZWxzZShjb21iaW5lZERmJFBQX0RldiA+IFRIUkVTSE9MRF9NSUxELCAxLCAwKQpgYGAKCmBgYHtyfQptb2RlbCA9IGxtZShQUF9EZXYgfiAKICAgICAgICAgICAgICBhYnMoUFBfRGV2XzJfU3RyYWlnaHQpCiAgICAgICAgICAgICAgKyBhYnMoUFBfRGV2XzNfU3RyYWlnaHQpCiAgICAgICAgICAgICAgKyBhYnMoUFBfRGV2XzJfVHVybmluZykgCiAgICAgICAgICAgICAgKyBhYnMoUFBfRGV2XzNfVHVybmluZykKICAgICAgICAgICAgICArIGZhY3RvcihBY3Rpdml0eSksIAogICAgICAgICAgICByYW5kb209fjF8U3ViamVjdCwKICAgICAgICAgICAgZGF0YT1jb21iaW5lZERmLAogICAgICAgICAgICBtZXRob2Q9IlJFTUwiKQoKIyBhbm92YShtb2RlbCkKc3VtbWFyeShtb2RlbCkKcGxvdChtb2RlbCkKYGBgCgpgYGB7cn0KbW9kZWwgPSBsbWUoUFBfRGV2IH4gCiAgICAgICAgICAgICAgYWJzKFBQX0Rldl8yX1R1cm5pbmcpCiAgICAgICAgICAgICAgKyBmYWN0b3IoQWN0aXZpdHkpLCAKICAgICAgICAgICAgcmFuZG9tPX4xfFN1YmplY3QsCiAgICAgICAgICAgIGRhdGE9Y29tYmluZWREZiwKICAgICAgICAgICAgbWV0aG9kPSJSRU1MIikKCiMgYW5vdmEobW9kZWwpCnN1bW1hcnkobW9kZWwpCnBsb3QobW9kZWwpCmBgYAoKYGBge3J9Cm1vZGVsID0gbG1lKFBQX0RldiB+IAogICAgICAgICAgICAgIFBQX0Rldl8yX1N0cmFpZ2h0ICsgCiAgICAgICAgICAgICAgUFBfRGV2XzNfU3RyYWlnaHQgKyAKICAgICAgICAgICAgICBQUF9EZXZfMV9UdXJuaW5nICsgCiAgICAgICAgICAgICAgUFBfRGV2XzJfVHVybmluZyArIAogICAgICAgICAgICAgIFBQX0Rldl8zX1R1cm5pbmcgKyAKICAgICAgICAgICAgICBTdGRfUFBfMiArIAogICAgICAgICAgICAgIFN0ZF9QUF8zICsKICAgICAgICAgICAgICBmYWN0b3IoQWN0aXZpdHkpLCAKICAgICAgICAgICAgcmFuZG9tPX4xfFN1YmplY3QsCiAgICAgICAgICAgIGRhdGE9Y29tYmluZWREZiwKICAgICAgICAgICAgbWV0aG9kPSJSRU1MIikKCiMgYW5vdmEobW9kZWwpCnN1bW1hcnkobW9kZWwpCnBsb3QobW9kZWwpCmBgYAoKIyMgTWFjaGluZSBMZWFybmluZwoKYGBge3J9CmNvbWJpbmVkRGYkUFBfRGV2IDwtIE5VTEwKCmNvbWJpbmVkRGYkU3ViamVjdCA8LSBOVUxMCmNvbWJpbmVkRGYkQWN0aXZpdHlfTk8gPC0gaWZlbHNlKGNvbWJpbmVkRGYkQWN0aXZpdHkgPT0gIk5PIiwgMSwgMCkKY29tYmluZWREZiRBY3Rpdml0eV9DIDwtIGlmZWxzZShjb21iaW5lZERmJEFjdGl2aXR5ID09ICJDIiwgMSwgMCkKY29tYmluZWREZiRBY3Rpdml0eV9NIDwtIGlmZWxzZShjb21iaW5lZERmJEFjdGl2aXR5ID09ICJNIiwgMSwgMCkKY29tYmluZWREZiRBY3Rpdml0eSA8LSBOVUxMCgpjb21iaW5lZERmJEluU2VnbWVudDEgPC0gaWZlbHNlKGNvbWJpbmVkRGYkU2VnbWVudCA9PSAxLCAxLCAwKQpjb21iaW5lZERmJEluU2VnbWVudDIgPC0gaWZlbHNlKGNvbWJpbmVkRGYkU2VnbWVudCA9PSAyLCAxLCAwKQpjb21iaW5lZERmJEluU2VnbWVudDMgPC0gaWZlbHNlKGNvbWJpbmVkRGYkU2VnbWVudCA9PSAzLCAxLCAwKQpjb21iaW5lZERmJEluU2VnbWVudDQgPC0gaWZlbHNlKGNvbWJpbmVkRGYkU2VnbWVudCA9PSA0LCAxLCAwKQpjb21iaW5lZERmJFNlZ21lbnQgPC0gTlVMTAoKY29tYmluZWREZiRDbGFzcyA8LSBpZmVsc2UoY29tYmluZWREZiRQUF9EZXZfR3JvdXAgPT0gMSwgVCwgRikKY29tYmluZWREZiRQUF9EZXZfR3JvdXAgPC0gTlVMTApgYGAKCmBgYHtyfQojIGxpYnJhcnkobWVmYSkKIyBjb21iaW5lZERmIDwtIHJlcChjb21iaW5lZERmLCAxMCkgCmBgYAoKYGBge3J9CiMgcz01NSwgZj00CgpzZXQuc2VlZCg1MTUxKSAKbl9mb2xkcyA8LSA1CnBhcmFtcyA8LSBwYXJhbSA8LSBsaXN0KG9iamVjdGl2ZSAgID0gImJpbmFyeTpsb2dpc3RpYyIsIAogICAgICAgICAgICAgICBib29zdGVyICAgICAgICAgID0gImdidHJlZSIsCiAgICAgICAgICAgICAgIGV2YWxfbWV0cmljICAgICAgPSAiYXVjIiwKICAgICAgICAgICAgICAgZXRhICAgICAgICAgICAgICA9IDAuMSwKICAgICAgICAgICAgICAgbWF4X2RlcHRoICAgICAgICA9IDgsCiAgICAgICAgICAgICAgIGFscGhhICAgICAgICAgICAgPSAxLAogICAgICAgICAgICAgICBsYW1iZGEgICAgICAgICAgID0gMCwKICAgICAgICAgICAgICAgZ2FtbWEgICAgICAgICAgICA9IDAuMywKICAgICAgICAgICAgICAgbWluX2NoaWxkX3dlaWdodCA9IDAuMywKICAgICAgICAgICAgICAgc3Vic2FtcGxlICAgICAgICA9IDEsCiAgICAgICAgICAgICAgIGNvbHNhbXBsZV9ieXRyZWUgPSAwLjUpCiAgICAgICAgICAgCiMgeGdiX20gPC0geGdiLmN2KCAgIHBhcmFtcyAgICAgICAgICAgICAgID0gcGFyYW0sCiMgICAgICAgICAgICAgICAgICAgZGF0YSA9IGFzLm1hdHJpeChjb21iaW5lZERmICU+JSBzZWxlY3QoLUNsYXNzKSkgLAojICAgICAgICAgICAgICAgICAgIGxhYmVsID0gIGNvbWJpbmVkRGYkQ2xhc3MsCiMgICAgICAgICAgICAgICAgICAgbnJvdW5kcyAgICAgICAgICAgICA9IDEwMCwKIyAgICAgICAgICAgICAgICAgICB2ZXJib3NlICAgICAgICAgICAgID0gRiwKIyAgICAgICAgICAgICAgICAgICBwcmVkaWN0aW9uICAgICAgICAgID0gVCwKIyAgICAgICAgICAgICAgICAgICBtYXhpbWl6ZSAgICAgICAgICAgID0gVCwKIyAgICAgICAgICAgICAgICAgICBuZm9sZCA9IG5fZm9sZHMsCiMgICAgICAgICAgICAgICAgICAgbWV0cmljcyAgPSAiYXVjIiwKIyAgICAgICAgICAgICAgICAgICBlYXJseV9zdG9wcGluZ19yb3VuZHMgPSAxMDAsCiMgICAgICAgICAgICAgICAgICAgc3RyYXRpZmllZCAgICAgICA9IEYsCiMgICAgICAgICAgICAgICAgICAgc2NhbGVfcG9zX3dlaWdodCA9IDAuNSkKIyAKIyAjIHhnYl9tJGV2YWx1YXRpb25fbG9nW3hnYl9tJGJlc3RfaXRlcmF0aW9uLCJ0ZXN0X2F1Y19tZWFuIl0KIyB4Z2JfbSRldmFsdWF0aW9uX2xvZ1t4Z2JfbSRiZXN0X2l0ZXJhdGlvbixdCgojIEVycm9yICAgICAgIAptbF9kYXRhIDwtIGFzLm1hdHJpeChjb21iaW5lZERmICU+JSBzZWxlY3QoLUNsYXNzKSkKCnhnYl9tIDwtIHhnYi5jdiggICBwYXJhbXMgICAgICAgICAgICAgICA9IHBhcmFtLAogICAgICAgICAgICAgICAgICBkYXRhID0gbWxfZGF0YSAsCiAgICAgICAgICAgICAgICAgIGxhYmVsID0gIGNvbWJpbmVkRGYkQ2xhc3MsCiAgICAgICAgICAgICAgICAgIG5yb3VuZHMgICAgICAgICAgICAgPSA1MDAsCiAgICAgICAgICAgICAgICAgIHZlcmJvc2UgICAgICAgICAgICAgPSBGLAogICAgICAgICAgICAgICAgICBwcmVkaWN0aW9uICAgICAgICAgID0gVCwKICAgICAgICAgICAgICAgICAgbWF4aW1pemUgICAgICAgICAgICA9IFQsCiAgICAgICAgICAgICAgICAgIG5mb2xkICAgICAgICAgICAgICAgPSBuX2ZvbGRzLAogICAgICAgICAgICAgICAgICBtZXRyaWNzICAgICAgICAgICAgID0gYygiYXVjIiwgImVycm9yIiksCiAgICAgICAgICAgICAgICAgIGVhcmx5X3N0b3BwaW5nX3JvdW5kcyA9IDEwMCwKICAgICAgICAgICAgICAgICAgc3RyYXRpZmllZCAgICAgICAgICAgID0gRiwKICAgICAgICAgICAgICAgICAgc2NhbGVfcG9zX3dlaWdodCAgICAgID0gMy4wNSkKCiMgeGdiX20kZXZhbHVhdGlvbl9sb2dbeGdiX20kYmVzdF9pdGVyYXRpb24sInRlc3RfYXVjX21lYW4iXQp4Z2JfbSRldmFsdWF0aW9uX2xvZ1t4Z2JfbSRiZXN0X2l0ZXJhdGlvbixdCgpgYGAKCmBgYHtyfQpsaWJyYXJ5KHBST0MpCgojIGl0ID0gd2hpY2gubWF4KHhnYl9tJGV2YWx1YXRpb25fbG9nJHRlc3RfYXVjX21lYW4pCiMgYmVzdC5pdGVyID0geGdiX20kZXZhbHVhdGlvbl9sb2ckaXRlcltpdF0KIyBiZXN0Lml0ZXIgCgpwbG90KHBST0M6OnJvYyhyZXNwb25zZSA9IGlmZWxzZShjb21iaW5lZERmJENsYXNzPT1ULCAxLCAwKSwKICAgICAgICAgICAgICAgcHJlZGljdG9yID0geGdiX20kcHJlZCwKICAgICAgICAgICAgICAgbGV2ZWxzPWMoMCwgMSkpLAogICAgIGx3ZD0xLjUpIApgYGAKCgoK